//Matthew Landrum
//Assignment 4.cpp

#include <time.h>
#include <iostream>
#include <stdlib.h>
#include <string>
#include <vector>
using namespace std;

struct Card {
	string value;	//Card's value in text
	string suit;	//Card's suit
	int numVal;		//Card's value as an integer (allows for comparison)
};

class Deck
{
public:
	Deck();							//create standard deck of 52 cards
	Deck(int deckSize);				//create deck of deckSize cards
	void outputDeck();				//output contents of deck
	Card dealCard();				//return top card and remove from deck
	Deck dealCard(int numOfCards);	//return deck of top numOfCards cards and remove from deck
	void addCard(Card myCard);		//add card to bottom of deck
	void shuffle();					//randomize deck contents
private:
	vector<Card> cards;				//Vector of cards.
};


int main()
{
	Deck mainDeck;
	mainDeck.outputDeck();
	mainDeck.shuffle();
	mainDeck.outputDeck();
	
	Card outputCard = mainDeck.dealCard();

	cout << "Your card is the " << outputCard.value << " of " << outputCard.suit << endl << endl;

	Deck outDeck = mainDeck.dealCard(5);

	cout << "New Deck: " << endl;
	outDeck.outputDeck();

	outDeck.shuffle();
	outDeck.outputDeck();
}

Deck::Deck()
//postcondition: a deck of cards of size "size"
{
	int suitNum;
	for (int i = 0; i < 52; i++) {
		Card thisCard;					//create card to store information
		thisCard.numVal = (i % 13) + 2;	//i% 13 gives 0-12, need to adjust up to min value of 2
		suitNum = i % 4;				//gives 0-3, or 4 different suits
		switch (suitNum) {
		case 0:
			thisCard.suit = "spades";
			break;
		case 1:
			thisCard.suit = "diamonds";
			break;
		case 2:
			thisCard.suit = "clubs";
			break;
		case 3:
			thisCard.suit = "hearts";
			break;
		}

		//set value for number cards
		if (thisCard.numVal < 11) {
			thisCard.value = to_string(thisCard.numVal);
		}
		//set value for cards greater than 9
		else {
			switch (thisCard.numVal) {
			case 11:
				thisCard.value = "J";
				break;
			case 12:
				thisCard.value = "Q";
				break;
			case 13:
				thisCard.value = "K";
				break;
			case 14:	//Aces high
				thisCard.value = "A";
				break;
			}
		}

		//track number of cards added
		cards.push_back(thisCard);
	}
}

Deck::Deck(int numOfCards)
//postcondition: a deck of cards of size "size"
{
	int suitNum;
	for (int i = 0; i < numOfCards; i++) {
		Card thisCard;					//create card to store information
		thisCard.numVal = (i % 13) + 2;	//i% 13 gives 0-12, need to adjust up to min value of 2
		suitNum = i % 4;				//gives 0-3, or 4 different suits
		switch (suitNum) {
		case 0:
			thisCard.suit = "spades";
			break;
		case 1:
			thisCard.suit = "diamonds";
			break;
		case 2:
			thisCard.suit = "clubs";
			break;
		case 3:
			thisCard.suit = "hearts";
			break;
		}

		//set value for number cards
		if (thisCard.numVal < 11) {
			thisCard.value = to_string(thisCard.numVal);
		}
		//set value for cards greater than 9
		else {
			switch (thisCard.numVal) {
			case 11:
				thisCard.value = "J";
				break;
			case 12:
				thisCard.value = "Q";
				break;
			case 13:
				thisCard.value = "K";
				break;
			case 14:	//Aces high
				thisCard.value = "A";
				break;
			}
		}

		//track number of cards added
		cards.push_back(thisCard);
	}
}

void Deck::outputDeck()
{
	//output intro
	cout << "Your cards are:" << endl;
	//output each card starting with top of deck
	for (int i = 0; i < cards.size(); i++) {
		cout << cards[i].value << " of " << cards[i].suit << endl;
	}
	//blank line
	cout << endl;
}

Card Deck::dealCard()
{
	//return card at front of vector
	Card myCard = cards[0];
	//remove card from vector
	cards.erase(cards.begin());
	return myCard;
}

Deck Deck::dealCard(int numOfCards)
{
	Deck myDeck(0);					//Create deck of size 0
	for (int i = 0; i < numOfCards; i++) {
		myDeck.addCard(cards[0]);
		cards.erase(cards.begin());
	}
	return myDeck;
}

void Deck::addCard(Card myCard) {
	//add new card to bottom of deck
	cards.push_back(myCard);
}

void Deck::shuffle() {
	//set random seed
	srand(time(0));

	//for each card up to current size
	for (int i = 0; i < cards.size(); i++) {
		//find random postiion between 0 and vector size -1
		int position = rand() % cards.size();

		//swap card in random position with current card
		Card temp = cards[position];
		cards[position] = cards[i];
		cards[i] = temp;
	}
}